package com.itee.monitor;

import com.itee.core.serial.SerialPortFactory;
import com.itee.core.serial.SerialSession;
import com.itee.core.util.StringCoder;
import com.itee.protocal.concent.AFN;
import com.itee.protocal.concent.ConcentPacket;
import com.itee.protocal.meta.Communication;
import com.itee.protocal.meter.MeterPacket;
import com.itee.protocal.meter.MeterProtocal;
import com.itee.street.entity.LampData;
import com.itee.street.entity.Term;
import org.apache.commons.lang.ArrayUtils;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.itee.protocal.concent.ConcentPacket.POS_BEGIN;
import static com.itee.protocal.concent.ConcentPacket.POS_END;


/**
 * Created by gonglei on 14-4-25.
 */
public class BaseTestSession extends SerialSession {

    //private ConcentPacket recvPacket;
    private String recvPacket;

    public BaseTestSession(IoSession session) {
        super(session);
    }

    @Override
    public void messageReceived(Object messages) {
        String concentPacket = messages.toString();
        this.recvPacket = concentPacket;
        synchronized (this) {
            notify();
        }
    }

    @Override
    public boolean doDecode(IoSession session, IoBuffer buff, ProtocolDecoderOutput out) throws Exception {
        buff.order(ByteOrder.LITTLE_ENDIAN);
        int start = buff.position();
        int len = 0;
        while (buff.hasRemaining()) {
            int pos = buff.position() - start;
            byte rb = buff.get();
            if (pos == 0) {
                if (rb != POS_BEGIN) {
                    return true;
                }
            } else if (pos == 2) {
                len = buff.getShort(1 + start) & 0x0000FFFF;
            } else if (pos == len - 1) {
                if (rb != POS_END) {
                    System.err.println("包非0x16结尾，丢弃该包");
                } else {
                    final int position = buff.position();
                    final int limit = buff.limit();
                    try {
                        buff.position(start);
                        buff.limit(position);
                        // 接收到完整数据包，解析
                        goDecoder(buff.slice(), out);
                    } finally {
                        buff.position(position);
                        buff.limit(limit);
                    }
                }
                return true;
            }
        }

        buff.position(start);
        return false;
    }

    private void goDecoder(IoBuffer buffer, ProtocolDecoderOutput out) {
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.get(); // ignore 0x68

        final int len = buffer.getShort() & 0x0000FFFF;

        byte ctrlByte = buffer.get();
        byte[] infoR = new byte[6];
        buffer.get(infoR);

        ConcentPacket concentPacket = new ConcentPacket();
        concentPacket.setCtrl(ctrlByte);
        concentPacket.setInfoR(infoR);
        int addrLen = 0;
        if (concentPacket.isCommunicateModuleCode()) {
            byte[] a1 = new byte[6];
            buffer.get(a1);
            concentPacket.setSource(a1);
            addrLen += 6;

            byte relayLevel = concentPacket.getRelayLevel();
            if (relayLevel > 0) {
                byte[][] relays = new byte[relayLevel][6];
                for (int i = 0; i < relayLevel; i++) {
                    relays[i] = new byte[6];
                    buffer.get(relays[i]);
                    addrLen += 6;
                }
                concentPacket.setRelays(relays);
            }

            byte[] a3 = new byte[6];
            buffer.get(a3);
            concentPacket.setDestination(a3);
            addrLen += 6;
        }

        concentPacket.setAfn(buffer.get());
        concentPacket.setDt1(buffer.get());
        concentPacket.setDt2(buffer.get());

        int dataLen = len - 6 - 6 - addrLen - 3;
        if (dataLen > 0) {
            byte[] data = new byte[dataLen];
            buffer.get(data);
            concentPacket.setDatas(data);
        }
        buffer.get(); // ignore 0x16;

        String receives = StringCoder.bytesToHexString(buffer.array(), buffer.limit(), " ");
        System.out.println(" << " + receives);

        out.write(concentPacket);
    }

    @Override
    public String getName() {
        return SerialPortFactory.PORT_TEST;
    }

    private String sendPacket(String packet, boolean wait) {
        recvPacket = null;
        sendPacket(packet.getBytes());
        if (wait) {
            synchronized (this) {
                try {
                    wait(5000);
                } catch (InterruptedException ignored) {
                }
            }
            if (recvPacket == null) {
                System.out.println("执行超时");
                return null;
            }
            return recvPacket;
        }
        return null;
    }

    private void sendPacket(String packet) {
        sendPacket(packet, false);
    }
    
//    public void dimmingLamp(int dimming, String concentUid, String termUid) {
//        ConcentPacket concentPacket = new ConcentPacket(false, true, Communication.CENTRALIZED_ROUTING_CARRIER);
//        concentPacket.setInfoR(false, true);
//        byte[] source = StringCoder.hexStringToByte(StringCoder.fillZeroLeft(concentUid, 12));
//        ArrayUtils.reverse(source);
//        concentPacket.setSource(source);
//        byte[] destination = StringCoder.hexStringToByte(termUid);
//        ArrayUtils.reverse(destination);
//        concentPacket.setDestination(destination);
//        concentPacket.setAfns(AFN.H13_RDF, 1);
//
//        byte[] datas = {0x01, 0x00, 0x00, 0x60, (byte) dimming};
//        byte[] dataBytes = new MeterPacket(termUid, (byte) 0x14, datas).toBytes();
//
//        ByteBuffer buffer = ByteBuffer.allocate(4 + dataBytes.length);
//        buffer.put(MeterProtocal.DLT2007.getProtocalByte());
//        buffer.put((byte) 0x00);
//        buffer.put((byte) 0x00);
//
//        buffer.put((byte) dataBytes.length);
//        buffer.put(dataBytes);
//        concentPacket.setDatas(buffer.array());
//        try {
//            sendPacket(concentPacket);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    /**
     * 参数区初始化
     */
//    public boolean clearArchive() {
//        ConcentPacket concentPacket = new ConcentPacket(false, true, Communication.CENTRALIZED_ROUTING_CARRIER);
//        concentPacket.setInfoR(false, false);
//        concentPacket.setAfns(AFN.H01, 2);
//
//        ConcentPacket recvPkt = sendPacket(concentPacket, true);
//        if (recvPkt != null) {
//            if (recvPkt.getAfn() == AFN.H00) {
//                if (recvPkt.getFn() == 1) {
//                    return true;
//                } else {
//                    System.out.println("参数区初始化返回否认帧");
//                }
//            } else {
//                System.out.println("参数区初始化帧收到的响应帧非确认/否认帧");
//            }
//        }
//        return false;
//    }

    /**
     * 下发档案
     *
     * @param lampTerms
     */
//    public boolean downloadArchive(List<Term> lampTerms) {
//        ConcentPacket concentPacket = new ConcentPacket(false, true, Communication.CENTRALIZED_ROUTING_CARRIER);
//        concentPacket.setInfoR(false, false);
//        concentPacket.setAfns(AFN.H11_RS, 1);
//        /**
//         * 从节点总数n（1字节）
//         * 每个从节点：地址（6字节）+协议类型（1字节）
//         */
//        ByteBuffer buffer = ByteBuffer.allocate(lampTerms.size() * 7 + 1);
//        buffer.put((byte) lampTerms.size());
//        /**
//         * 设置每个从节点通信协议类型
//         */
//        for (Term dau : lampTerms) {
//            byte[] uidBcd = StringCoder.hexStringToByte(dau.getTermUid());
//            ArrayUtils.reverse(uidBcd);
//            buffer.put(uidBcd);
//            buffer.put((byte) 0x02);
//        }
//        concentPacket.setDatas(buffer.array());
//
//        ConcentPacket recvPkt = sendPacket(concentPacket, true);
//        if (recvPkt != null) {
//            if (recvPkt.getAfn() == AFN.H00) {
//                if (recvPkt.getFn() == 1) {
//                    return true;
//                } else {
//                    System.out.println("下发档案返回否认帧");
//                }
//            } else {
//                System.out.println("下发档案收到的响应帧非确认/否认帧");
//            }
//        }
//        return false;
//    }
    public boolean verifyArchive(String Err) {

        String recvPkt = sendPacket(Err, true);
        String recvOk = ".*ok.*";    //ok
        
        if (recvPkt != null) {
            System.out.println("<<"+recvPkt);
        }
        return false;
    }
    
    
    
    public String ReadUidArchive(String Cmd) {

        String recvPkt = sendPacket(Cmd, true);
        return recvPkt.substring(recvPkt.indexOf(":"));
    }
    
    
    /**
     * 读取单灯数据
     *
     * @param concentUid
     * @param termUid
     */
    public String writeCmdToBl(String Cmd) {
       
        String recvPkt = sendPacket(Cmd, true);
        
        return recvPkt;
    }
    /**
     * 读取从节点数量
     */
//    public int[] readNodeNum() {
//        ConcentPacket concentPacket = new ConcentPacket(false, true, Communication.CENTRALIZED_ROUTING_CARRIER);
//        concentPacket.setInfoR(false, false);
//        concentPacket.setAfns(AFN.H10, 1);
//        ConcentPacket recvPkt = sendPacket(concentPacket, true);
//        if (recvPkt != null) {
//            if (recvPkt.getAfn() == AFN.H10 && recvPkt.getFn() == 1) {
//                ByteBuffer buffer = ByteBuffer.wrap(recvPkt.getDatas());
//                buffer.order(ByteOrder.LITTLE_ENDIAN);
//
//                int num = buffer.getShort();
//                int max = buffer.getShort();
//
//                return new int[]{num, max};
//            } else {
//                System.out.println("读取从节点数量的响应帧不正确");
//            }
//        }
//        return null;
//    }

    /**
     * 读取从节点信息
     */
//    public List<Term> readArchives(int start, int num) {
//        ConcentPacket concentPacket = new ConcentPacket(false, true, Communication.CENTRALIZED_ROUTING_CARRIER);
//        concentPacket.setInfoR(false, false);
//        concentPacket.setAfns(AFN.H10, 2);
//
//        ByteBuffer buffer = ByteBuffer.allocate(3);
//        buffer.order(ByteOrder.LITTLE_ENDIAN);
//        buffer.putShort((short) start);
//        buffer.put((byte) num);
//        concentPacket.setDatas(buffer.array());
//
//        ConcentPacket recvPkt = sendPacket(concentPacket, true);
//        if (recvPkt != null) {
//            if (recvPkt.getAfn() == AFN.H10 && recvPkt.getFn() == 2) {
//
//                List<Term> concentArchives = new ArrayList<>();
//
//                buffer = ByteBuffer.wrap(recvPkt.getDatas());
//                buffer.order(ByteOrder.LITTLE_ENDIAN);
//
//                // 从节点总数
//                int nodeNum = buffer.getShort();
//                System.out.println("从节点总数：" + nodeNum);
//
//                // 本次应答的从节点数量
//                int responseNum = buffer.get();
//
//                for (int i = 0; i < responseNum; i++) {
//                    byte[] addrBytes = new byte[6];
//                    buffer.get(addrBytes);
//
//                    ArrayUtils.reverse(addrBytes);
//                    String address = StringCoder.bytesToHexString(addrBytes);
//                    concentArchives.add(new Term(address, i + start + 1));
//                }
//
//                return concentArchives;
//            } else {
//                System.out.println("读取从节点信息的响应帧不正确");
//            }
//        }
//        return null;
//    }

    /**
     * 读取单灯数据
     *
     * @param concentUid
     * @param termUid
     */
//    public LampData readLampData(String concentUid, String termUid) {
//        ConcentPacket concentPacket = new ConcentPacket(false, true, Communication.CENTRALIZED_ROUTING_CARRIER);
//        concentPacket.setInfoR(false, true);
//        byte[] source = StringCoder.hexStringToByte(StringCoder.fillZeroLeft(concentUid, 12));
//        ArrayUtils.reverse(source);
//        concentPacket.setSource(source);
//        byte[] destination = StringCoder.hexStringToByte(termUid);
//        ArrayUtils.reverse(destination);
//        concentPacket.setDestination(destination);
//        concentPacket.setAfns(AFN.H13_RDF, 1);
//
//        byte[] datas = {0x01, 0x00, 0x00, 0x61};
//        byte[] dataBytes = new MeterPacket(termUid, (byte) 0x14, datas).toBytes();
//
//        ByteBuffer buffer = ByteBuffer.allocate(4 + dataBytes.length);
//        buffer.put(MeterProtocal.DLT2007.getProtocalByte());
//        buffer.put((byte) 0x00);
//        buffer.put((byte) 0x00);
//
//        buffer.put((byte) dataBytes.length);
//        buffer.put(dataBytes);
//        concentPacket.setDatas(buffer.array());
//
//        ConcentPacket recvPkt = sendPacket(concentPacket, true);
//        if (recvPkt != null) {
//            if (recvPkt.getAfn() == AFN.H13_RDF && recvPkt.getFn() == 1) {
//                byte[] data = recvPkt.getDatas();
//                ByteBuffer bf= ByteBuffer.wrap(data);
//                bf.getInt();
//                bf.get();//0x68
//                byte[] address=new byte[6];
//                bf.get(address);//读终端地址
//                bf.get();//0x68
//                byte cmd= bf.get();//ctrl
//                byte length=bf.get();
//                byte[] lampDatas=new byte[length];
//                bf.get(lampDatas);//645 data
//                for (int i = 0; i < lampDatas.length; i++) {
//                    lampDatas[i]= (byte) (lampDatas[i]-0x33);
//                }
//                if (Arrays.equals(Arrays.copyOfRange(lampDatas, 0, 4), datas)) {
//                    ByteBuffer buff = ByteBuffer.wrap(lampDatas, 4, lampDatas.length-4);
//                    buff.order(ByteOrder.LITTLE_ENDIAN);
//
//                    // 单节点状态 %
//                    byte state = buff.get();
//                    // 报警数据标志
//                    byte[] alarmFlag = new byte[4];
//                    buff.get(alarmFlag);
//                    // 电压 0.1V
//                    double voltage = buff.getShort() * 0.1; // V
//                    // 电流 mA
//                    double current = buff.getInt() * 0.001; // A
//                    // 功率 W
//                    double power = buff.getShort() * 0.001; // kW
//                    // 功率因素 %
//                    int powerFactor = buff.get();
//                    // 温度 0.1度
//                    double temp = (buff.get() & 0x00FF) * 0.1; // 度
//                    // 电量示值 wh
//                    double powerConsume = buff.getInt() * 0.0001; // kWh
//                    // 亮灯时长 分钟
//                    int lightTime = buff.getInt();
//
//                    LampData lampData = new LampData();
//                    lampData.setDimming(state);
//                    lampData.parseAlarmBit(alarmFlag);
//                    lampData.setVoltage(voltage);
//                    lampData.setCurrent(current);
//                    lampData.setPower(power);
//                    lampData.setPowerFactor(powerFactor);
//                    lampData.setTemperature(temp);
//                    lampData.setPowerConsume(powerConsume);
//                    lampData.setLightTime(lightTime);
//                    lampData.setCreateTime(new Date());
//                    System.out.println(lampData);
//
//                    return lampData;
//                } else {
//                    System.out.println("读取单灯数据的响应帧不正确");
//                }
//            } else {
//                System.out.println("读取单灯数据的响应帧不正确");
//            }
//        }
//        return null;
//    }
}
